home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk.zip / RE_CMPL.C < prev    next >
C/C++ Source or Header  |  1991-04-07  |  7KB  |  322 lines

  1.  
  2. /********************************************
  3. re_cmpl.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the Awk programming language as defined in
  8. Aho, Kernighan and Weinberger, The AWK Programming Language,
  9. Addison-Wesley, 1988.
  10.  
  11. See the accompaning file, LIMITATIONS, for restrictions
  12. regarding modification and redistribution of this
  13. program in source or binary form.
  14. ********************************************/
  15.  
  16. /* $Log:    re_cmpl.c,v $
  17.  * Revision 2.1  91/04/08  08:23:45  brennan
  18.  * VERSION 0.97
  19.  * 
  20. */
  21.  
  22.  
  23. /*  re_cmpl.c  */
  24.  
  25. #include "mawk.h"
  26. #include "memory.h"
  27. #include "scan.h"
  28. #include "regexp.h"
  29. #include "repl.h"
  30. #include  <string.h>
  31.  
  32. static  CELL *PROTO( REPL_compile, (STRING *) ) ;
  33.  
  34. typedef struct re_node {
  35. STRING  *sval ;
  36. PTR     re ;
  37. struct re_node *link ;
  38. }  RE_NODE ;
  39.  
  40. static RE_NODE *re_list ;  /* a list of compiled regular expressions */
  41.  
  42.  
  43. PTR re_compile( sval )
  44.   STRING *sval ;
  45. { register RE_NODE *p ;
  46.   RE_NODE *q ;
  47.   char *s ;
  48.  
  49.   /* search list */
  50.   s = sval->str ;
  51.   p = re_list ;
  52.   q = (RE_NODE *) 0 ;
  53.   while ( p )
  54.     if ( strcmp(s, p->sval->str) == 0 )  /* found */
  55.         if ( !q ) /* already at front */  goto _return ;
  56.         else /* delete from list for move to front */
  57.         { q->link = p->link ; goto found ; }
  58.     else
  59.     { q = p ; p = p->link ; }
  60.  
  61.   /* not found */
  62.   p = (RE_NODE *) zmalloc( sizeof(RE_NODE) ) ;
  63.   p->sval = sval ;
  64.   sval->ref_cnt++ ;
  65.   if( !(p->re = REcompile(s)) )
  66.   { errmsg(0, "regular expression compile failed (%s)\n%s\n" ,
  67.                REerrlist[REerrno] , s) ;  mawk_exit(1) ; }
  68.  
  69. found :
  70. /* insert p at the front of the list */
  71.   p->link = re_list ; re_list = p ;
  72.  
  73. _return :
  74.   
  75. #ifdef  DEBUG
  76.   if ( dump_RE )  REmprint(p->re, stderr) ;
  77. #endif
  78.   return p->re ;
  79. }
  80.  
  81.  
  82.  
  83. /* this is only used by da() */
  84.  
  85. char *re_uncompile( m )
  86.   PTR  m ;
  87. { register RE_NODE *p ;
  88.  
  89.   for( p = re_list ; p ; p = p->link )
  90.         if ( p->re == m )  return  p->sval->str ;
  91. #ifdef  DEBUG
  92.   bozo("non compiled machine") ;
  93. #endif
  94. }
  95.   
  96.  
  97.  
  98. /*=================================================*/
  99. /*  replacement  operations   */
  100.  
  101. /* create a replacement CELL from a STRING *  */
  102.  
  103. static CELL *REPL_compile( sval )
  104.   STRING  *sval ;
  105. { int i = 0 ;
  106.   register char *p = sval->str ;
  107.   register char *q ;
  108.   char *xbuff ;
  109.   CELL *cp ;
  110.  
  111.   q = xbuff = (char *) zmalloc( sval->len + 1 ) ;
  112.  
  113.   while ( 1 )
  114.   {
  115.       switch( *p )
  116.       {
  117.         case  0  :  *q = 0 ;
  118.                     goto  done  ;
  119.  
  120.         case  '\\':
  121.                 if ( p[1] == '&' )
  122.                 { *q++ = '&' ; p += 2 ; continue ; }
  123.                 else  break ;
  124.  
  125.         case  '&':
  126.                 /* if empty we don't need to make a node */
  127.                 if ( q != xbuff )
  128.                 { *q = 0 ;
  129.                   temp_buff.ptr_buff[i++] = (PTR) new_STRING(xbuff) ;
  130.                 }
  131.                 /* and a null node for the '&'  */
  132.                 temp_buff.ptr_buff[i++] = (PTR) 0  ;
  133.                 /*  reset  */
  134.                 p++ ;  q = xbuff ;
  135.                 continue ;
  136.  
  137.         default :
  138.                 break ;
  139.       }
  140.  
  141.       *q++ = *p++ ;
  142.   }
  143.  
  144. done :   
  145.   /* if we have one empty string it will get made now */
  146.   if ( q > xbuff || i == 0 )
  147.           temp_buff.ptr_buff[i++] = (PTR) new_STRING(xbuff) ;
  148.  
  149.   if ( i > MAX_FIELD )
  150.       overflow("replacement pieces", MAX_FIELD) ;
  151.  
  152.   cp = new_CELL() ;
  153.   if ( i == 1 )
  154.   {
  155.     cp->type = C_REPL ;
  156.     cp->ptr = temp_buff.ptr_buff[0] ;
  157.   }
  158.   else
  159.   {
  160.     STRING **sp = (STRING**)
  161.                   (cp->ptr = zmalloc(sizeof(STRING *)*i)) ;
  162.     int j = 0 ;
  163.  
  164.     while ( j < i ) *sp++ = (STRING *)temp_buff.ptr_buff[j++] ;
  165.  
  166.     cp->type = C_REPLV ;
  167.     cp->vcnt = i ;
  168.   }
  169.   zfree(xbuff, sval->len+1) ;
  170.   return cp ;
  171. }
  172.  
  173. /* free memory used by a replacement CELL  */
  174.  
  175. void  repl_destroy( cp )
  176.   register CELL *cp ;
  177. { register STRING **p ;
  178.   unsigned cnt ;
  179.  
  180.   if ( cp->type == C_REPL )  free_STRING(string(cp)) ;
  181.   else  /* an C_REPLV  */
  182.   {
  183.     p = (STRING **) cp->ptr ;
  184.     for( cnt = cp->vcnt ; cnt ; cnt--) 
  185.     {
  186.       if ( *p ) free_STRING( *p ) ;
  187.       p++ ;
  188.     }
  189.     zfree( cp->ptr, cp->vcnt * sizeof(STRING *) ) ;
  190.   }
  191. }
  192.  
  193. /* copy a C_REPLV cell to another CELL */
  194.  
  195. CELL  *replv_cpy( target, source )
  196.   CELL *target , *source ;
  197. { STRING **t, **s ;
  198.   unsigned cnt ;
  199.  
  200.   target->type = C_REPLV ;
  201.   target->vcnt = source->vcnt ;
  202.  
  203.   target->ptr = (PTR) zmalloc( target->vcnt * sizeof(STRING *) ) ;
  204.   cnt = target->vcnt ;
  205.   t = (STRING **) target->ptr ;
  206.   s = (STRING **) source->ptr ;
  207.   while ( cnt-- )
  208.   { 
  209.     if ( *t = *s++ )   (*t)->ref_cnt++ ;
  210.     t++ ;
  211.   }
  212.   return target ;
  213. }
  214.  
  215. /* here's our old friend linked linear list with move to the front
  216.    for compilation of replacement CELLs  */
  217.  
  218. typedef  struct repl_node {
  219.   struct repl_node  *link ;
  220.   STRING  *sval  ;  /* the input */
  221.   CELL    *cp ;  /* the output */
  222. }  REPL_NODE  ;
  223.  
  224. static  REPL_NODE  *repl_list ;
  225.  
  226. /* search the list (with move to the front) for a compiled
  227.    separator.
  228.    return a ptr to a CELL (C_REPL or C_REPLV)
  229. */
  230.  
  231. CELL *repl_compile( sval )
  232.   STRING *sval ;
  233. { register REPL_NODE *p ;
  234.   REPL_NODE *q ;
  235.   char *s ;
  236.  
  237.   /* search the list */
  238.   s = sval->str ;
  239.   p = repl_list ;
  240.   q = (REPL_NODE *) 0 ;
  241.   while ( p )
  242.     if ( strcmp(s, p->sval->str) == 0 )  /* found */
  243.         if ( !q ) /* already at front */  return p->cp ;
  244.         else /* delete from list for move to front */
  245.         { q->link = p->link ; goto found ; }
  246.     else
  247.     { q = p ; p = p->link ; }
  248.  
  249.   /* not found */
  250.   p = (REPL_NODE *) zmalloc( sizeof(REPL_NODE) ) ;
  251.   p->sval = sval ;
  252.   sval->ref_cnt++ ;
  253.   p->cp = REPL_compile(sval) ;
  254.  
  255. found :
  256. /* insert p at the front of the list */
  257.   p->link = repl_list ; repl_list = p ;
  258.   return p->cp ;
  259. }
  260.  
  261. /* return the string for a CELL or type REPL or REPLV,
  262.    this is only used by da()  */
  263.  
  264. char *repl_uncompile( cp )
  265.   CELL *cp ;
  266. {
  267.   register REPL_NODE *p = repl_list ;
  268.  
  269.   if ( cp->type == C_REPL )
  270.     while ( p )
  271.       if ( p->cp->type == C_REPL &&
  272.            p->cp->ptr  == cp->ptr )   return p->sval->str ;
  273.       else  p = p->link ;
  274.   else
  275.     while ( p )
  276.       if ( p->cp->type == C_REPLV &&
  277.            memcmp( cp->ptr, p->cp->ptr, cp->vcnt * sizeof(STRING*)) 
  278.            == 0  )   return  p->sval->str ;
  279.       else  p = p->link ;
  280.  
  281.   bozo("unable to uncompile an repl") ;
  282. }
  283.  
  284. /*
  285.   convert a C_REPLV to  C_REPL
  286.      replacing the &s with sval
  287. */
  288.  
  289. CELL  *replv_to_repl( cp, sval)
  290.   CELL *cp ; STRING *sval ;
  291. { register STRING **p ;
  292.   STRING **sblock = (STRING **) cp->ptr ;
  293.   unsigned cnt , vcnt = cp->vcnt ;
  294.   unsigned len ;
  295.   char *target ;
  296.  
  297. #ifdef  DEBUG
  298.   if ( cp->type != C_REPLV ) bozo("not replv") ;
  299. #endif
  300.  
  301.   p = sblock ; cnt = vcnt ; len = 0 ;
  302.   while ( cnt-- )
  303.       if ( *p )  len += (*p++)->len ;
  304.       else
  305.       { *p++ = sval ; sval->ref_cnt++ ; len += sval->len ; }
  306.  
  307.   cp->type = C_REPL ;
  308.   cp->ptr = (PTR) new_STRING((char *) 0, len) ;
  309.  
  310.   p = sblock ; cnt = vcnt ; target = string(cp)->str ;
  311.   while ( cnt-- )
  312.   { (void) memcpy(target, (*p)->str, (*p)->len) ;
  313.     target += (*p)->len ;
  314.     free_STRING(*p) ;
  315.     p++ ;
  316.   }
  317.  
  318.   zfree( sblock, vcnt * sizeof(STRING *) ) ;
  319.   return cp ;
  320. }
  321.  
  322.